<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>导航守卫 | Vue Router</title>
    <meta name="description" content="Vue.js 的官方路由">
    <link rel="stylesheet" href="static/css/style.720cf281.css">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/Home.50302e7a.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/ui-custom.4cf347f1.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/ui-custom.8de93204.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/AlgoliaSearchBox.80d79d6b.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/app.47b74ea6.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/zh_guide_advanced_navigation-guards.md.2c59c5ad.lean.js">
    
    <link rel="icon" href="static/picture/logo.png">
  <meta name="wwads-cn-verify" content="7e7757b1e12abcb736ab9a754ffb617a">
  <script src="static/js/thesemetrics@latest.js" async=""></script>
  <meta name="twitter:title" content="导航守卫 | Vue Router">
  <meta property="og:title" content="导航守卫 | Vue Router">
  </head>
  <body>
    <div id="app"><div class="main-container" data-v-46b24580=""><!----><!--[--><div class="theme"><header class="nav-bar" data-v-675d8756=""><div class="sidebar-button" data-v-675d8756=""><svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewbox="0 0 448 512"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class=""></path></svg></div><a class="nav-bar-title" href="index1.html" aria-label="Vue Router, back to home" data-v-675d8756="" data-v-4a583abe=""><!----> Vue Router</a><div class="flex-grow" data-v-675d8756=""></div><div class="nav" data-v-675d8756=""><nav class="nav-links" data-v-675d8756="" data-v-eab3edfe=""><!--[--><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item active" href="index2.html" data-v-b8818f8c="">教程 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item" href="index3.html" data-v-b8818f8c="">API 参考 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-dropdown-link" data-v-eab3edfe="" data-v-56bf3a3f=""><button class="button" data-v-56bf3a3f=""><span class="button-text" data-v-56bf3a3f="">v4.x</span><span class="right button-arrow" data-v-56bf3a3f=""></span></button><ul class="dialog" data-v-56bf3a3f=""><!--[--><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item isExternal" href="index4.html" target="_blank" rel="noopener noreferrer" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">v3.x</span><span class="icon" data-v-bbc27490=""><svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-bbc27490=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">更新日志 <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><div class="item" data-v-eab3edfe=""><div class="nav-dropdown-link" data-v-eab3edfe="" data-v-56bf3a3f=""><button class="button" data-v-56bf3a3f=""><span class="button-text" data-v-56bf3a3f="">选择语言</span><span class="right button-arrow" data-v-56bf3a3f=""></span></button><ul class="dialog" data-v-56bf3a3f=""><!--[--><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item" href="navigation-guards1.html" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">English</span><span class="icon" data-v-bbc27490=""><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item active" href="" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">中文</span><span class="icon" data-v-bbc27490=""><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">GitHub <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div></nav></div><!--[--><!--[--><div class="algolia-search-box" id="docsearch"></div><!--]--><!--]--></header><aside class="sidebar" data-v-83e92a68=""><nav class="nav-links nav" data-v-83e92a68="" data-v-eab3edfe=""><!--[--><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item active" href="index2.html" data-v-b8818f8c="">教程 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item" href="index3.html" data-v-b8818f8c="">API 参考 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-dropdown-link" data-v-eab3edfe="" data-v-56bf3a3f=""><button class="button" data-v-56bf3a3f=""><span class="button-text" data-v-56bf3a3f="">v4.x</span><span class="right button-arrow" data-v-56bf3a3f=""></span></button><ul class="dialog" data-v-56bf3a3f=""><!--[--><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item isExternal" href="index4.html" target="_blank" rel="noopener noreferrer" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">v3.x</span><span class="icon" data-v-bbc27490=""><svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-bbc27490=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">更新日志 <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><div class="item" data-v-eab3edfe=""><div class="nav-dropdown-link" data-v-eab3edfe="" data-v-56bf3a3f=""><button class="button" data-v-56bf3a3f=""><span class="button-text" data-v-56bf3a3f="">选择语言</span><span class="right button-arrow" data-v-56bf3a3f=""></span></button><ul class="dialog" data-v-56bf3a3f=""><!--[--><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item" href="navigation-guards1.html" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">English</span><span class="icon" data-v-bbc27490=""><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item active" href="" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">中文</span><span class="icon" data-v-bbc27490=""><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">GitHub <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div></nav><!--[--><!--[--><div class="sponsors sponsors-top" data-v-46b24580=""><span data-v-46b24580="">Platinum Sponsors</span><!--[--><a href="javascript:;" target="_blank" rel="noopener" data-v-46b24580=""><img src="https://posva-sponsors.pages.dev/logos/fincliplogo_black_svg.svg" alt="Finogeeks" data-v-46b24580=""></a><!--]--></div><!--]--><!--]--><ul class="sidebar-links" data-v-83e92a68=""><!--[--><li class="sidebar-link"><a class="sidebar-link-item" href="introduction.html">介绍</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="installation.html">安装</a><!----></li><li class="sidebar-link"><p class="sidebar-link-item">基础</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="index2.html">入门</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="dynamic-matching.html">动态路由匹配</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="route-matching-syntax.html">路由的匹配语法</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="nested-routes.html">嵌套路由</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="navigation.html">编程式导航</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="named-routes.html">命名路由</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="named-views.html">命名视图</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="redirect-and-alias.html">重定向和别名</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="passing-props.html">路由组件传参</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="history-mode.html">不同的历史记录模式</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">进阶</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item active" href="">导航守卫</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#全局前置守卫">全局前置守卫</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#可选的第三个参数-next">可选的第三个参数 next</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="#全局解析守卫">全局解析守卫</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#全局后置钩子">全局后置钩子</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#路由独享的守卫">路由独享的守卫</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#组件内的守卫">组件内的守卫</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#可用的配置-api">可用的配置 API</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#使用组合-api">使用组合 API</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="#完整的导航解析流程">完整的导航解析流程</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="meta.html">路由元信息</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="data-fetching.html">数据获取</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="composition-api.html">组合式 API</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="transitions.html">过渡动效</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="scroll-behavior.html">滚动行为</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="lazy-loading.html">路由懒加载</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="extending-router-link.html">扩展 RouterLink</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="navigation-failures.html">导航故障</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="dynamic-routing.html">动态路由</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="index.html">从 Vue2 迁移</a><!----></li><!--]--></ul><!--[--><!--[--><div class="sponsors" data-v-46b24580=""><span data-v-46b24580="">Sponsors</span><!--[--><a href="javascript:;" target="_blank" rel="noopener" data-v-46b24580=""><img src="https://posva-sponsors.pages.dev/logos/vuejobs.svg" alt="VueJobs" data-v-46b24580=""></a><!--]--></div><!--]--><!--]--></aside><div class="sidebar-mask"></div><main class="page" data-v-7eddb2c4=""><div class="container" data-v-7eddb2c4=""><!--[--><!--[--><div id="ads-container"><div class="carbon-ads" ref_key="el" data-v-5941b830=""></div></div><!--]--><!--[--><!--]--><!--]--><div style="position:relative;" class="content" data-v-7eddb2c4=""><div><h1 id="导航守卫" tabindex="-1">导航守卫 <a class="header-anchor" href="#导航守卫" aria-hidden="true">#</a></h1><p>正如其名，vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中：全局的，单个路由独享的，或者组件级的。</p><h2 id="全局前置守卫" tabindex="-1">全局前置守卫 <a class="header-anchor" href="#全局前置守卫" aria-hidden="true">#</a></h2><p>你可以使用 <code>router.beforeEach</code> 注册一个全局前置守卫：</p><div class="language-js"><pre><code><span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

router<span class="token punctuation">.</span><span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
  <span class="token comment">// 返回 false 以取消导航</span>
  <span class="token keyword">return</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>当一个导航触发时，全局前置守卫按照创建顺序调用。守卫是异步解析执行，此时导航在所有守卫 resolve 完之前一直处于<strong>等待中</strong>。</p><p>每个守卫方法接收两个参数：</p><ul><li><strong><code>to</code></strong>: 即将要进入的目标 <a href="index3.html#routelocationnormalized">用一种标准化的方式</a></li><li><strong><code>from</code></strong>: 当前导航正要离开的路由 <a href="index3.html#routelocationnormalized">用一种标准化的方式</a></li></ul><p>可以返回的值如下:</p><ul><li><code>false</code>: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮)，那么 URL 地址会重置到 <code>from</code> 路由对应的地址。</li><li>一个<a href="index3.html#routelocationraw">路由地址</a>: 通过一个路由地址跳转到一个不同的地址，就像你调用 <a href="index3.html#push"><code>router.push()</code></a> 一样，你可以设置诸如 <code>replace: true</code> 或 <code>name: &#39;home&#39;</code> 之类的配置。当前的导航被中断，然后进行一个新的导航，就和 <code>from</code> 一样。</li></ul><p>如果遇到了意料之外的情况，可能会抛出一个 <code>Error</code>。这会取消导航并且调用 <a href="index3.html#onerror"><code>router.onError()</code></a> 注册过的回调。</p><p>如果什么都没有，<code>undefined</code> 或返回 <code>true</code>，<strong>则导航是有效的</strong>，并调用下一个导航守卫</p><p>以上所有都同 <strong><code>async</code> 函数</strong> 和 Promise 工作方式一样：</p><div class="language-js"><pre><code>router<span class="token punctuation">.</span><span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// canUserAccess() 返回 `true` 或 `false`</span>
  <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token function">canUserAccess</span><span class="token punctuation">(</span>to<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h3 id="可选的第三个参数-next" tabindex="-1">可选的第三个参数 <code>next</code> <a class="header-anchor" href="#可选的第三个参数-next" aria-hidden="true">#</a></h3><p>在之前的 Vue Router 版本中，也是可以使用 <em>第三个参数</em> <code>next</code> 的。这是一个常见的错误来源，可以通过 <a href="javascript:;" target="_blank" rel="noopener noreferrer">RFC</a> 来消除错误。然而，它仍然是被支持的，这意味着你可以向任何导航守卫传递第三个参数。在这种情况下，<strong>确保 <code>next</code></strong> 在任何给定的导航守卫中都被<strong>严格调用一次</strong>。它可以出现多于一次，但是只能在所有的逻辑路径都不重叠的情况下，否则钩子永远都不会被解析或报错。这里有一个在用户未能验证身份时重定向到<code>/login</code>的<strong>错误用例</strong>：</p><div class="language-js"><pre><code><span class="token comment">// BAD</span>
router<span class="token punctuation">.</span><span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> from<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>to<span class="token punctuation">.</span>name <span class="token operator">!==</span> <span class="token string">&#39;Login&#39;</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>isAuthenticated<span class="token punctuation">)</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;Login&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token comment">// 如果用户未能验证身份，则 `next` 会被调用两次</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>下面是正确的版本:</p><div class="language-js"><pre><code><span class="token comment">// GOOD</span>
router<span class="token punctuation">.</span><span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> from<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>to<span class="token punctuation">.</span>name <span class="token operator">!==</span> <span class="token string">&#39;Login&#39;</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>isAuthenticated<span class="token punctuation">)</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;Login&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token keyword">else</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h2 id="全局解析守卫" tabindex="-1">全局解析守卫 <a class="header-anchor" href="#全局解析守卫" aria-hidden="true">#</a></h2><p>你可以用 <code>router.beforeResolve</code> 注册一个全局守卫。这和 <code>router.beforeEach</code> 类似，因为它在 <strong>每次导航</strong>时都会触发，但是确保在导航被确认之前，<strong>同时在所有组件内守卫和异步路由组件被解析之后，解析守卫就被正确调用</strong>。这里有一个例子，确保用户可以访问<a href="meta.html">自定义 meta</a> 属性 <code>requiresCamera</code> 的路由：</p><div class="language-js"><pre><code>router<span class="token punctuation">.</span><span class="token function">beforeResolve</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token parameter">to</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>to<span class="token punctuation">.</span>meta<span class="token punctuation">.</span>requiresCamera<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">try</span> <span class="token punctuation">{</span>
      <span class="token keyword">await</span> <span class="token function">askForCameraPermission</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>error <span class="token keyword">instanceof</span> <span class="token class-name">NotAllowedError</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// ... 处理错误，然后取消导航</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token comment">// 意料之外的错误，取消导航并把错误传给全局处理器</span>
        <span class="token keyword">throw</span> error
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p><code>router.beforeResolve</code> 是获取数据或执行任何其他操作（如果用户无法进入页面时你希望避免执行的操作）的理想位置。</p><h2 id="全局后置钩子" tabindex="-1">全局后置钩子 <a class="header-anchor" href="#全局后置钩子" aria-hidden="true">#</a></h2><p>你也可以注册全局后置钩子，然而和守卫不同的是，这些钩子不会接受 <code>next</code> 函数也不会改变导航本身：</p><div class="language-js"><pre><code>router<span class="token punctuation">.</span><span class="token function">afterEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">sendToAnalytics</span><span class="token punctuation">(</span>to<span class="token punctuation">.</span>fullPath<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。</p><p>它们也反映了 <a href="navigation-failures.html">navigation failures</a> 作为第三个参数：</p><div class="language-js"><pre><code>router<span class="token punctuation">.</span><span class="token function">afterEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> from<span class="token punctuation">,</span> failure</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>failure<span class="token punctuation">)</span> <span class="token function">sendToAnalytics</span><span class="token punctuation">(</span>to<span class="token punctuation">.</span>fullPath<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>了解更多关于 navigation failures 的信息在<a href="navigation-failures.html">它的指南</a>中。</p><h2 id="路由独享的守卫" tabindex="-1">路由独享的守卫 <a class="header-anchor" href="#路由独享的守卫" aria-hidden="true">#</a></h2><p>你可以直接在路由配置上定义 <code>beforeEnter</code> 守卫：</p><div class="language-js"><pre><code><span class="token keyword">const</span> routes <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;/users/:id&#39;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">component</span><span class="token operator">:</span> UserDetails<span class="token punctuation">,</span>
    <span class="token function-variable function">beforeEnter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token comment">// reject the navigation</span>
      <span class="token keyword">return</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>
</code></pre></div><p><code>beforeEnter</code> 守卫 <strong>只在进入路由时触发</strong>，不会在 <code>params</code>、<code>query</code> 或 <code>hash</code> 改变时触发。例如，从 <code>/users/2</code> 进入到 <code>/users/3</code> 或者从 <code>/users/2#info</code> 进入到 <code>/users/2#projects</code>。它们只有在 <strong>从一个不同的</strong> 路由导航时，才会被触发。</p><p>你也可以将一个函数数组传递给 <code>beforeEnter</code>，这在为不同的路由重用守卫时很有用：</p><div class="language-js"><pre><code><span class="token keyword">function</span> <span class="token function">removeQueryParams</span><span class="token punctuation">(</span><span class="token parameter">to</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>to<span class="token punctuation">.</span>query<span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> to<span class="token punctuation">.</span>path<span class="token punctuation">,</span> <span class="token literal-property property">query</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token literal-property property">hash</span><span class="token operator">:</span> to<span class="token punctuation">.</span>hash <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">removeHash</span><span class="token punctuation">(</span><span class="token parameter">to</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>to<span class="token punctuation">.</span>hash<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> to<span class="token punctuation">.</span>path<span class="token punctuation">,</span> <span class="token literal-property property">query</span><span class="token operator">:</span> to<span class="token punctuation">.</span>query<span class="token punctuation">,</span> <span class="token literal-property property">hash</span><span class="token operator">:</span> <span class="token string">&#39;&#39;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> routes <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;/users/:id&#39;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">component</span><span class="token operator">:</span> UserDetails<span class="token punctuation">,</span>
    <span class="token literal-property property">beforeEnter</span><span class="token operator">:</span> <span class="token punctuation">[</span>removeQueryParams<span class="token punctuation">,</span> removeHash<span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;/about&#39;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">component</span><span class="token operator">:</span> UserDetails<span class="token punctuation">,</span>
    <span class="token literal-property property">beforeEnter</span><span class="token operator">:</span> <span class="token punctuation">[</span>removeQueryParams<span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>
</code></pre></div><p>请注意，你也可以通过使用<a href="meta.html">路径 meta 字段</a>和<a href="#global-before-guards">全局导航守卫</a>来实现类似的行为。</p><h2 id="组件内的守卫" tabindex="-1">组件内的守卫 <a class="header-anchor" href="#组件内的守卫" aria-hidden="true">#</a></h2><p>最后，你可以在路由组件内直接定义路由导航守卫(传递给路由配置的)</p><h3 id="可用的配置-api" tabindex="-1">可用的配置 API <a class="header-anchor" href="#可用的配置-api" aria-hidden="true">#</a></h3><p>你可以为路由组件添加以下配置：</p><ul><li><code>beforeRouteEnter</code></li><li><code>beforeRouteUpdate</code></li><li><code>beforeRouteLeave</code></li></ul><div class="language-js"><pre><code><span class="token keyword">const</span> UserDetails <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">...</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
  <span class="token function">beforeRouteEnter</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 在渲染该组件的对应路由被验证前调用</span>
    <span class="token comment">// 不能获取组件实例 `this` ！</span>
    <span class="token comment">// 因为当守卫执行时，组件实例还没被创建！</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">beforeRouteUpdate</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 在当前路由改变，但是该组件被复用时调用</span>
    <span class="token comment">// 举例来说，对于一个带有动态参数的路径 `/users/:id`，在 `/users/1` 和 `/users/2` 之间跳转的时候，</span>
    <span class="token comment">// 由于会渲染同样的 `UserDetails` 组件，因此组件实例会被复用。而这个钩子就会在这个情况下被调用。</span>
    <span class="token comment">// 因为在这种情况发生的时候，组件已经挂载好了，导航守卫可以访问组件实例 `this`</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">beforeRouteLeave</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 在导航离开渲染该组件的对应路由时调用</span>
    <span class="token comment">// 与 `beforeRouteUpdate` 一样，它可以访问组件实例 `this`</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p><code>beforeRouteEnter</code> 守卫 <strong>不能</strong> 访问 <code>this</code>，因为守卫在导航确认前被调用，因此即将登场的新组件还没被创建。</p><p>不过，你可以通过传一个回调给 <code>next</code> 来访问组件实例。在导航被确认的时候执行回调，并且把组件实例作为回调方法的参数：</p><div class="language-js"><pre><code><span class="token function">beforeRouteEnter</span> <span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> from<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token parameter">vm</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 通过 `vm` 访问组件实例</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>注意 <code>beforeRouteEnter</code> 是支持给 <code>next</code> 传递回调的唯一守卫。对于 <code>beforeRouteUpdate</code> 和 <code>beforeRouteLeave</code> 来说，<code>this</code> 已经可用了，所以<em>不支持</em> 传递回调，因为没有必要了：</p><div class="language-js"><pre><code><span class="token function">beforeRouteUpdate</span> <span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// just use `this`</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> to<span class="token punctuation">.</span>params<span class="token punctuation">.</span>name
<span class="token punctuation">}</span>
</code></pre></div><p>这个 <strong>离开守卫</strong> 通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回 <code>false</code> 来取消。</p><div class="language-js"><pre><code><span class="token function">beforeRouteLeave</span> <span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> answer <span class="token operator">=</span> window<span class="token punctuation">.</span><span class="token function">confirm</span><span class="token punctuation">(</span><span class="token string">&#39;Do you really want to leave? you have unsaved changes!&#39;</span><span class="token punctuation">)</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>answer<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="使用组合-api" tabindex="-1">使用组合 API <a class="header-anchor" href="#使用组合-api" aria-hidden="true">#</a></h3><p>如果你正在使用<a href="javascript:;" target="_blank" rel="noopener noreferrer">组合 API 和 <code>setup</code> 函数</a>来编写组件，你可以通过 <code>onBeforeRouteUpdate</code> 和 <code>onBeforeRouteLeave</code> 分别添加 update 和 leave 守卫。 请参考<a href="composition-api.html#导航守卫">组合 API 部分</a>以获得更多细节。</p><h2 id="完整的导航解析流程" tabindex="-1">完整的导航解析流程 <a class="header-anchor" href="#完整的导航解析流程" aria-hidden="true">#</a></h2><ol><li>导航被触发。</li><li>在失活的组件里调用 <code>beforeRouteLeave</code> 守卫。</li><li>调用全局的 <code>beforeEach</code> 守卫。</li><li>在重用的组件里调用 <code>beforeRouteUpdate</code> 守卫(2.2+)。</li><li>在路由配置里调用 <code>beforeEnter</code>。</li><li>解析异步路由组件。</li><li>在被激活的组件里调用 <code>beforeRouteEnter</code>。</li><li>调用全局的 <code>beforeResolve</code> 守卫(2.5+)。</li><li>导航被确认。</li><li>调用全局的 <code>afterEach</code> 钩子。</li><li>触发 DOM 更新。</li><li>调用 <code>beforeRouteEnter</code> 守卫中传给 <code>next</code> 的回调函数，创建好的组件实例会作为回调函数的参数传入。</li></ol></div></div><footer class="page-footer" data-v-7eddb2c4="" data-v-fb8d84c6=""><div class="edit" data-v-fb8d84c6=""><div class="edit-link" data-v-fb8d84c6="" data-v-1ed99556=""><a class="link" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-1ed99556="">Suggest changes to this page <svg class="icon outbound icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-1ed99556=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="updated" data-v-fb8d84c6=""><!----></div></footer><div class="next-and-prev-link" data-v-7eddb2c4="" data-v-38ede35f=""><div class="container" data-v-38ede35f=""><div class="prev" data-v-38ede35f=""><a class="link" href="history-mode.html" data-v-38ede35f=""><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon icon-prev" data-v-38ede35f=""><path d="M19,11H7.4l5.3-5.3c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0l-7,7c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.2-0.1,0.5,0,0.8c0.1,0.1,0.1,0.2,0.2,0.3l7,7c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L7.4,13H19c0.6,0,1-0.4,1-1S19.6,11,19,11z"></path></svg><span class="text" data-v-38ede35f="">不同的历史记录模式</span></a></div><div class="next" data-v-38ede35f=""><a class="link" href="meta.html" data-v-38ede35f=""><span class="text" data-v-38ede35f="">路由元信息</span><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon icon-next" data-v-38ede35f=""><path d="M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"></path></svg></a></div></div></div><!--[--><!--[--><!--]--><!--[--><div class="buy-sell-ads" data-v-4ce5ad17=""><div class="bsa-cpc" data-v-4ce5ad17=""></div></div><!--]--><!--]--></div></main></div><!----><!--]--></div></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"api_index.md\":\"d2104c47\",\"guide_advanced_composition-api.md\":\"c4a35a0b\",\"guide_advanced_data-fetching.md\":\"b840e67c\",\"guide_advanced_dynamic-routing.md\":\"652f0e44\",\"guide_advanced_extending-router-link.md\":\"9af8914a\",\"guide_advanced_lazy-loading.md\":\"8d710c99\",\"guide_advanced_meta.md\":\"a024ec3d\",\"guide_advanced_navigation-failures.md\":\"57e1a0e2\",\"guide_advanced_navigation-guards.md\":\"7d263b2b\",\"guide_advanced_scroll-behavior.md\":\"84f7daa3\",\"guide_advanced_transitions.md\":\"85553476\",\"guide_essentials_dynamic-matching.md\":\"fa6babaa\",\"guide_essentials_history-mode.md\":\"56f164ed\",\"guide_essentials_named-routes.md\":\"94d29abc\",\"guide_essentials_named-views.md\":\"c0d13d46\",\"guide_essentials_navigation.md\":\"c1db3764\",\"guide_essentials_nested-routes.md\":\"0c92c29e\",\"guide_essentials_passing-props.md\":\"c283ba51\",\"guide_essentials_redirect-and-alias.md\":\"ff823362\",\"guide_essentials_route-matching-syntax.md\":\"8d709abb\",\"guide_index.md\":\"adc6171f\",\"guide_migration_index.md\":\"b3d45cf2\",\"index.md\":\"58761df1\",\"installation.md\":\"80dcd302\",\"introduction.md\":\"e6a9eb47\",\"zh_api_index.md\":\"9540fde2\",\"zh_guide_advanced_composition-api.md\":\"c9cfee63\",\"zh_guide_advanced_data-fetching.md\":\"c83aef48\",\"zh_guide_advanced_dynamic-routing.md\":\"10e27a0f\",\"zh_guide_advanced_extending-router-link.md\":\"4de5dd4e\",\"zh_guide_advanced_lazy-loading.md\":\"bc3ba5ac\",\"zh_guide_advanced_meta.md\":\"9802cc2e\",\"zh_guide_advanced_navigation-failures.md\":\"02c8440d\",\"zh_guide_advanced_navigation-guards.md\":\"2c59c5ad\",\"zh_guide_advanced_scroll-behavior.md\":\"22a11e87\",\"zh_guide_advanced_transitions.md\":\"f4039441\",\"zh_guide_essentials_dynamic-matching.md\":\"e6594e44\",\"zh_guide_essentials_history-mode.md\":\"beb89b31\",\"zh_guide_essentials_named-routes.md\":\"66c05082\",\"zh_guide_essentials_named-views.md\":\"9aae5c1b\",\"zh_guide_essentials_navigation.md\":\"c0faee1f\",\"zh_guide_essentials_nested-routes.md\":\"e1852582\",\"zh_guide_essentials_passing-props.md\":\"030d2081\",\"zh_guide_essentials_redirect-and-alias.md\":\"ea0856be\",\"zh_guide_essentials_route-matching-syntax.md\":\"e907166f\",\"zh_guide_index.md\":\"bb134cde\",\"zh_guide_migration_index.md\":\"c448fcd8\",\"zh_index.md\":\"90ac17e3\",\"zh_installation.md\":\"7a5d9568\",\"zh_introduction.md\":\"6a2f4e36\"}")</script>
    <script type="module" async="" src="static/js/app.47b74ea6.js"></script>
    
  </body>
</html>